package com.koron.css2.common.utils;

import com.koron.css2.common.bean.FileProBean;
import com.koron.css2.common.bean.MultipartContentBean;
import org.apache.commons.fileupload.FileItem;
import org.apache.commons.fileupload.disk.DiskFileItemFactory;
import org.apache.commons.fileupload.servlet.ServletFileUpload;
import org.apache.commons.io.IOUtils;
import org.apache.http.Consts;
import org.apache.http.HttpEntity;
import org.apache.http.HttpResponse;
import org.apache.http.NameValuePair;
import org.apache.http.client.ClientProtocolException;
import org.apache.http.client.config.RequestConfig;
import org.apache.http.client.entity.UrlEncodedFormEntity;
import org.apache.http.client.methods.CloseableHttpResponse;
import org.apache.http.client.methods.HttpGet;
import org.apache.http.client.methods.HttpPost;
import org.apache.http.entity.ContentType;
import org.apache.http.entity.StringEntity;
import org.apache.http.entity.mime.HttpMultipartMode;
import org.apache.http.entity.mime.MultipartEntityBuilder;
import org.apache.http.entity.mime.content.FileBody;
import org.apache.http.entity.mime.content.StringBody;
import org.apache.http.impl.client.CloseableHttpClient;
import org.apache.http.impl.client.HttpClients;
import org.apache.http.message.BasicNameValuePair;
import org.apache.http.util.EntityUtils;
import org.apache.logging.log4j.LogManager;
import org.apache.logging.log4j.Logger;

import javax.servlet.http.HttpServletRequest;
import java.io.*;
import java.net.HttpURLConnection;
import java.net.URL;
import java.net.URLConnection;
import java.net.URLEncoder;
import java.nio.charset.Charset;
import java.util.*;
import java.util.Map.Entry;

public class HttpUtils {

	private static Logger log = LogManager.getLogger(HttpUtils.class);

	private static final String NEWLINE = "\r\n"; // 换行，或者说是回车

	private static final String BOUNDARY = "---------------------------7e222e13115bc"; // 固定的前缀

	private static final String PREFIX = "--";
	
	public static String sendGetForm(String url, Map<String, String> params) {
        try (CloseableHttpClient httpClient = HttpClients.createDefault()){
        	String param = "";
            if (params != null) {
            	Set<Entry<String, String>> set = params.entrySet();
            	for(Entry<String, String> entry : set) {
            		if(param.isEmpty()) {
            			param = entry.getKey() + "=" + entry.getValue();
            		}else {
            			param = param + "&" + entry.getKey() + "=" + entry.getValue();
            		}
            	}
            }
            url = param.isEmpty() ? url : url + "?" + param;
        	HttpGet httpGet = new HttpGet(url);
            try(CloseableHttpResponse response = httpClient.execute(httpGet)){
            	 return EntityUtils.toString(response.getEntity(), "utf-8");
            }
        } catch (Exception e) {
        	log.error("发送get请求失败", e);
			throw new RuntimeException("发送get请求失败", e);
        }
	}
	
	public static String sendPostForm(String url, Map<String, String> params) {
        try (CloseableHttpClient httpClient = HttpClients.createDefault()){
            HttpPost httpPost = new HttpPost(url);
            httpPost.setHeader("Content-Type", "application/x-www-form-urlencoded; charset=UTF-8");
            if (params != null) {
                List<NameValuePair> nameValuePairs = new ArrayList<>();
                for (String key : params.keySet()) {
                	nameValuePairs.add(new BasicNameValuePair(key, params.get(key)));
                }
                httpPost.setEntity(new UrlEncodedFormEntity(nameValuePairs,"UTF-8"));
            }
            try(CloseableHttpResponse response = httpClient.execute(httpPost)){
            	 return EntityUtils.toString(response.getEntity(), "utf-8");
            }  
        } catch (Exception e) {
        	log.error("发送post请求失败", e);
			throw new RuntimeException("发送post请求失败", e);
        }
	}
	
	public static String sendPost2(String url, Map<String, String> params) {
   	 PrintWriter out = null;
        BufferedReader in = null;
        String result = "";
        try {
            URL realUrl = new URL(url);
            URLConnection conn = realUrl.openConnection();
            conn.setRequestProperty("accept", "*/*");
            conn.setRequestProperty("connection", "Keep-Alive");
            conn.setRequestProperty("user-agent", "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1;SV1)");
            conn.setDoOutput(true);
            conn.setDoInput(true);
            out = new PrintWriter(new OutputStreamWriter(conn.getOutputStream(),"utf-8"));
            String param = "";
            if (params != null) {
            	Set<Entry<String, String>> set = params.entrySet();
            	for(Entry<String, String> entry : set) {
            		if(param.isEmpty()) {
            			param = entry.getKey() + "=" + entry.getValue();
            		}else {
            			param = param + "&" + entry.getKey() + "=" + entry.getValue();
            		}
            	}
            }
            out.print(param);
            out.flush();
            in = new BufferedReader(new InputStreamReader(conn.getInputStream(),"utf-8"));
            String line;
            while ((line = in.readLine()) != null) {
                result += line;
            }
        } catch (IOException e) {
        	throw new RuntimeException("发送 POST 请求失败!", e) ;
        }
        finally{
            try{
                if(out!=null){
                    out.close();
                }
                if(in!=null){
                    in.close();
                }
            }
            catch(IOException ex){
                ex.printStackTrace();
            }
        }
        return result;
   }
	public static String sendPostQueryAndJson(String url, Map<String, String> params, String json) {
        try (CloseableHttpClient httpClient = HttpClients.createDefault()){
            String param = "";
            if (params != null) {
            	Set<Entry<String, String>> set = params.entrySet();
            	for(Entry<String, String> entry : set) {
            		if(param.isEmpty()) {
            			param = entry.getKey() + "=" + entry.getValue();
            		}else {
            			param = param + "&" + entry.getKey() + "=" + entry.getValue();
            		}
            	}
            }
            url = param.isEmpty() ? url : url + "?" + param;
            HttpPost httpPost = new HttpPost(url);
            StringEntity entity = new StringEntity(json, ContentType.APPLICATION_JSON);
            httpPost.setEntity(entity);
            try(CloseableHttpResponse response = httpClient.execute(httpPost)){
            	 return EntityUtils.toString(response.getEntity(), "utf-8");
            }
        } catch (Exception e) {
        	log.error("发送post请求失败", e);
			throw new RuntimeException("发送post请求失败", e);
        }
	}
	
    public static String sendPostJson(String url, String json) {
        try (CloseableHttpClient httpClient = HttpClients.createDefault()){
            HttpPost httpPost = new HttpPost(url);
            StringEntity entity = new StringEntity(json, ContentType.APPLICATION_JSON);
            httpPost.setEntity(entity);
            try(CloseableHttpResponse response = httpClient.execute(httpPost)){
            	 return EntityUtils.toString(response.getEntity(), "utf-8");
            }
        } catch (Exception e) {
        	log.error("发送post请求失败", e);
			throw new RuntimeException("发送post请求失败", e);
        }
	}
	
	public static String sendPostJson(String url, Map<String, String> headers, String json) {
        try (CloseableHttpClient httpClient = HttpClients.createDefault()){
            HttpPost httpPost = new HttpPost(url);
            StringEntity entity = new StringEntity(json, ContentType.APPLICATION_JSON);
            httpPost.setEntity(entity);
			// 浏览器表示
	        httpPost.addHeader("User-Agent", "Mozilla/5.0 (Windows; U; Windows NT 5.1; en-US; rv:1.7.6)");
	        // 传输的类型
	        httpPost.addHeader("Content-Type", "application/json");
	        //追加的头部信息
            headers.forEach((k, v) -> {
            	httpPost.setHeader(k, v);
            });
	        // 执行请求
            try(CloseableHttpResponse response = httpClient.execute(httpPost)){
            	 return EntityUtils.toString(response.getEntity(), "utf-8");
            }
        } catch (Exception e) {
        	log.error("发送post请求失败", e);
			throw new RuntimeException("发送post请求失败", e);
        }
	}
	
	
	
	public static String upload(File[] files, String url, Map<String, String> data) {
		CloseableHttpClient httpClient = null;
		CloseableHttpResponse response = null;
		try {
			
			httpClient = HttpClients.createDefault();

			HttpPost httpPost = new HttpPost(url);

			FileBody[] bins = new FileBody[files.length];

			for (int i = 0; i < files.length; i++) {
				bins[i] = new FileBody(files[i]);
			}

			MultipartEntityBuilder builder = MultipartEntityBuilder.create();

			for (FileBody bin : bins) {
				builder.addPart("file", bin);
			}

			Set<Entry<String, String>> entrys = data.entrySet();
			for (Entry<String, String> entry : entrys) {
				builder.addPart(entry.getKey(), new StringBody(entry.getValue(), ContentType.create("text/plain", Consts.UTF_8)));
			}

			HttpEntity reqEntity = builder.build();

			httpPost.setEntity(reqEntity);

			response = httpClient.execute(httpPost);

			HttpEntity resEntity = response.getEntity();

			if (resEntity != null) {
				log.info("Response content length: {}", resEntity.getContentLength());
				log.info("Response content：{}", EntityUtils.toString(resEntity, Charset.forName("UTF-8")));
			}
			EntityUtils.consume(resEntity);
			return EntityUtils.toString(resEntity, Charset.forName("UTF-8"));
		} catch (Exception e) {
			log.error("上传文件请求失败!{}", e);
			throw new RuntimeException("上传文件请求失败", e);
		} finally {
			try {
				if (response != null) {
					response.close();
				}
			} catch (IOException e) {
				e.printStackTrace();
			}

			try {
				if (httpClient != null) {
					httpClient.close();
				}
			} catch (IOException e) {
				e.printStackTrace();
			}
		}
	}

	public static String upload(String url, FileProBean file) {
		HttpURLConnection httpConn = null;
		BufferedInputStream bis = null;
		DataOutputStream dos = null;
		ByteArrayOutputStream baos = new ByteArrayOutputStream();
		try {
			URL urlObj = new URL(url);
			httpConn = (HttpURLConnection) urlObj.openConnection();
			httpConn.setDoInput(true);
			httpConn.setDoOutput(true);
			httpConn.setRequestMethod("POST");
			httpConn.setUseCaches(false);
			httpConn.setRequestProperty("Connection", "Keep-Alive");
			httpConn.setRequestProperty("Accept", "*/*");
			httpConn.setRequestProperty("Accept-Encoding", "gzip, deflate");
			httpConn.setRequestProperty("Cache-Control", "no-cache");
			httpConn.setRequestProperty("Content-Type", "multipart/form-data; boundary=" + BOUNDARY);
			httpConn.setRequestProperty("User-Agent", "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1; SV1; .NET CLR 2.0.50727; .NET CLR 3.0.04506.30)");
			httpConn.connect();
			dos = new DataOutputStream(httpConn.getOutputStream());
			if (file.getData() != null && !file.getData().isEmpty()) { // 这时请求中的普通参数，键值对类型的，相当于上面分析的请求中的username，可能有多个
				Set<Entry<String, String>> entrys = file.getData().entrySet();
				for (Entry<String, String> entry : entrys) {
					String key = entry.getKey(); // 键，相当于上面分析的请求中的username
					String value = entry.getValue(); // 值，相当于上面分析的请求中的sdafdsa
					dos.writeBytes(PREFIX + BOUNDARY + NEWLINE); // 像请求体中写分割线，就是前缀+分界线+换行
					dos.writeBytes("Content-Disposition: form-data; " + "name=\"" + key + "\"" + NEWLINE); // 拼接参数名，格式就是Content-Disposition:
					dos.writeBytes(NEWLINE); // 空行，一定不能少，键和值之间有一个固定的空行
					dos.writeBytes(URLEncoder.encode(value.toString(), "UTF-8")); // 将值写入
					dos.writeBytes(NEWLINE); // 换行
				} 
			}
			for (MultipartContentBean multipart : file.getMultipart()) {
				if (multipart.getBytes().length > 0) {
					String filename = URLEncoder.encode(multipart.getFileName(), "UTF8");
					filename = filename.replace("+", "%20");
					dos.writeBytes(PREFIX + BOUNDARY + NEWLINE);
					dos.writeBytes("Content-Disposition: form-data; " + "name=\"" + "file" + "\"" + "; filename=\"" + filename + "\"" + NEWLINE);
					dos.writeBytes("Content-Type:" + multipart.getContentType() + NEWLINE);
					dos.writeBytes(NEWLINE);
					dos.write(multipart.getBytes()); 
					dos.writeBytes(NEWLINE); 
				}
			}
			dos.writeBytes(PREFIX + BOUNDARY + PREFIX + NEWLINE);
			dos.writeBytes(NEWLINE);
			dos.flush();

			byte[] buffer = new byte[10 * 1024];
			int c = 0;
			if (httpConn.getResponseCode() == 200) {
				bis = new BufferedInputStream(httpConn.getInputStream());
				while ((c = bis.read(buffer)) != -1) {
					baos.write(buffer, 0, c);
					baos.flush();
				}
			}
			return IOUtils.toString(buffer, "UTF-8");
		} catch (Exception e) {
			throw new RuntimeException("上传文件请求失败", e);
		} finally {
			try {
				if (dos != null)
					dos.close();
				if (bis != null)
					bis.close();
				if (baos != null)
					baos.close();
				httpConn.disconnect();
			} catch (Exception e) {
				e.printStackTrace();
			}
		}
	}

	public static FileProBean getFiles(HttpServletRequest request) {
		try {
			List<MultipartContentBean> multiparts = new ArrayList<MultipartContentBean>();
			Map<String, String> data = new HashMap<>();
			FileProBean file = new FileProBean();
			DiskFileItemFactory factory = new DiskFileItemFactory();
			ServletFileUpload upload = new ServletFileUpload(factory);
			upload.setHeaderEncoding("UTF-8");
			if (!ServletFileUpload.isMultipartContent(request)) {
				throw new RuntimeException("不是 Multipart 请求类型");
			}
			List<FileItem> items = upload.parseRequest(request);
			for (FileItem item : items) {
				if (!item.isFormField()){
					MultipartContentBean multipart = new MultipartContentBean();
					String filename = item.getName();
					if (filename == null) {
						continue;
					}
					filename = filename.substring(filename.lastIndexOf("\\") + 1);
					InputStream input = item.getInputStream();
					byte[] bytes = IOUtils.toByteArray(input);
					multipart.setFileName(filename);
					multipart.setContentType(item.getContentType());
					multipart.setBytes(bytes);
					multiparts.add(multipart);
				}else {
					 data.put(item.getFieldName(), item.getString("UTF-8"));
				}
				file.setData(data);
				file.setMultipart(multiparts);
				item.delete();
			}
			return file;
		} catch (Exception e) {
			throw new RuntimeException("获取文件失败", e);
		}
	}

	public static void upload(String url,File file,String filename) {
		CloseableHttpClient httpclient = HttpClients.createDefault();
		try {
			HttpPost httppost = new HttpPost(url);
			RequestConfig requestConfig = RequestConfig.custom().setConnectTimeout(200000).setSocketTimeout(200000).build();
			httppost.setConfig(requestConfig);
			FileBody bin = new FileBody(file);
			StringBody comment = new StringBody(filename, ContentType.TEXT_PLAIN);
			HttpEntity reqEntity = MultipartEntityBuilder.create().addPart("file", bin).addPart("filename", comment).build();
			httppost.setEntity(reqEntity);
			System.out.println("executing request " + httppost.getRequestLine());
			CloseableHttpResponse response = httpclient.execute(httppost);
			try {
				System.out.println(response.getStatusLine());
				HttpEntity resEntity = response.getEntity();
				if (resEntity != null) {
					String responseEntityStr = EntityUtils.toString(response.getEntity());
					System.out.println(responseEntityStr);
				}
				EntityUtils.consume(resEntity);
			} finally {
				response.close();
			}
		} catch (ClientProtocolException e) {
			e.printStackTrace();
		} catch (IOException e) {
			e.printStackTrace();
		} finally {
			try {
				httpclient.close();
			} catch (IOException e) {
				e.printStackTrace();
			}
		}
	}

	public static String fileUpload(byte[] buffer, String url, String classId) throws IOException {
		//创建HttpClient对象
		CloseableHttpClient client = HttpClients.createDefault();
		//构建POST请求   请求地址请更换为自己的。
		//1)
		HttpPost post = new HttpPost(url);
		InputStream inputStream = new ByteArrayInputStream(buffer);
		try {
			//文件路径请换成自己的
			//2)
			MultipartEntityBuilder builder = MultipartEntityBuilder.create();
			builder.setMode(HttpMultipartMode.BROWSER_COMPATIBLE);
			//第一个参数为 相当于 Form表单提交的file框的name值 第二个参数就是我们要发送的InputStream对象了
			//第三个参数是文件名
			//3)
			builder.addBinaryBody("fileName", inputStream, ContentType.create("multipart/form-data"),  classId + ".pdf");
			//4)构建请求参数 普通表单项
            /*StringBody stringBody = new StringBody("12", ContentType.MULTIPART_FORM_DATA);
            builder.addPart("id",stringBody);*/
			HttpEntity entity = builder.build();
			post.setEntity(entity);
			//发送请求
			HttpResponse response = client.execute(post);
			entity = response.getEntity();
			if (entity != null) {
				inputStream = entity.getContent();
				//转换为字节输入流
				BufferedReader br = new BufferedReader(new InputStreamReader(inputStream, Consts.UTF_8));
				String body = null;
				while ((body = br.readLine()) != null) {

					return body;
				}
			}
		} catch (FileNotFoundException e) {
			e.printStackTrace();
		} catch (ClientProtocolException e) {
			e.printStackTrace();
		} catch (IOException e) {
			e.printStackTrace();
		} finally {
			if (inputStream != null) {
				try {
					inputStream.close();
				} catch (IOException e) {
					e.printStackTrace();
				}
			}
		}
		return null;
	}

}
